Skip to content

fix: ensure RecordCopyPolicy and RecordInstantiationPolicy set for all embeddable records - #2799

Closed
hantsy wants to merge 2 commits into
eclipse-ee4j:masterfrom
hantsy:fix/record-embeddedid-support-master
Closed

fix: ensure RecordCopyPolicy and RecordInstantiationPolicy set for all embeddable records#2799
hantsy wants to merge 2 commits into
eclipse-ee4j:masterfrom
hantsy:fix/record-embeddedid-support-master

Conversation

@hantsy

@hantsy hantsy commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@
Fixes #2656IllegalAccessException: Can not set final field when using Java records as @Embeddable with @EmbeddedId or @Embedded.

Root Cause

ClassDescriptor.initialize() wraps the record detection (lines 3984–4003) in a if (!isMethodAccess) guard. For embeddable records whose mappings use method access (the default, since record accessor methods like id() are methods), RecordCopyPolicy and RecordInstantiationPolicy were never initialized.

Without RecordCopyPolicy, the UOW working copy clone path calls PersistenceEntityCopyPolicy._persistence_shallow_clone() which uses Object.clone() — this fails on records because their fields are final.

Without RecordInstantiationPolicy, buildNewInstance() falls back to the default no-arg-constructor path, which also fails because records have no no-arg constructor.

Fix

Move the record-specific policy initialization outside the !isMethodAccess guard. Records always need RecordCopyPolicy and RecordInstantiationPolicy regardless of access type, because their fields are always final.

Additional change

The empty catch (Exception ignore) was masking failures during instantiation policy setup. Added a comment explaining the intent.

Test

Added TestRecordEmbeddable with:

  • RecordId(UUID id)@Embeddable record used as @EmbeddedId
  • RecordValue(String description, int amount)@Embeddable record used as @Embedded
  • RecordEntity — entity exercising both
  • testPersistAndFind — persist → clear → find → verify
  • testMerge — persist → clear → merge with updated values

Without the fix, both tests throw IllegalAccessException during persist or merge.
@

@hantsy

hantsy commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

I used Claude Code to analyze the issue and create this PR and try to resolve #2656

@hantsy
hantsy force-pushed the fix/record-embeddedid-support-master branch from 5015563 to b3b6a9f Compare August 1, 2026 00:54
@hantsy
hantsy force-pushed the fix/record-embeddedid-support-master branch 2 times, most recently from bc45ec2 to c72e643 Compare August 16, 2026 03:13
Records are immutable value types, so EclipseLink must construct and copy
them through their canonical constructor and record components rather than
through no-arg construction and field reflection.

- Set RecordCopyPolicy and RecordInstantiationPolicy for record descriptors
  regardless of field or method access.
- Build record primary key classes via their canonical constructor in
  CMPPolicy.createPrimaryKeyInstance() (fixes record @EmbeddedId/@IdClass).
- Replace record aggregates with a clone instead of merging field-by-field
  in AggregateMapping.mergeChangesIntoObject().

Co-Authored-By: Claude <noreply@anthropic.com>
@hantsy
hantsy force-pushed the fix/record-embeddedid-support-master branch from c72e643 to 5fc024d Compare August 16, 2026 05:05
@hantsy

hantsy commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Superseded — this has been split into three focused PRs (one fix + test each):

Closing this in favor of the three.

@hantsy hantsy closed this Aug 23, 2026
@hantsy
hantsy deleted the fix/record-embeddedid-support-master branch August 23, 2026 01:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

EmbededID with an Embeddable UUID field failed

1 participant